﻿#pragma once
#include "ADFGlobal.h"
#include "AsTestAlgorithmExecutor.h"
#include "ATConfigUi.h"
#include "AsTableModelRow.h"
#include "AsPluginTableModelRow.h"
#include "AsPlugin.h"
#include "AsBasicMethod.h"
#include <QStringList>

using ConfigUiCtor=std::function<ATConfigUi*(void)>;
using ParamCtor= std::function <AsJsonObject*(void)>;
using ModelRowCtor= std::function < AsPluginTableModelRow*(void)>;
using ATDetectFn = std::function<int(const cv::Mat&, AsJsonObject*, AsPluginTableModelRow*)>;
/**
 * @desc 输出参数
 */
class AsTestOutputArg : public AsPluginArgsBase {
public:
	ConfigUiCtor uiCtor;			//ui包装器构造器
	ParamCtor paramCtor;			//参数构造器
	ModelRowCtor modelItemCtor;	//数据模型构造器

	QMap<QString, ATDetectFn> detectFnMap;		//函数表
	QStringList fnList;							//函数列表
};

//提供去封装化函数
template<typename _DETECTOR>
int detectFn(const cv::Mat& input, AsJsonObject* pParamWrapper, AsPluginTableModelRow* pItem)
{
	if (std::is_base_of<AsTestAlgorithmExecutor, _DETECTOR>()) {
		AsTestAlgorithmExecutor* pDetector = new _DETECTOR();
		pDetector->beforeDetect(input);
		int iRet = pDetector->detectFn(input, pParamWrapper, pItem);
		if (pItem != nullptr) {
			pItem->setResult(iRet);
		}
		pDetector->afterDetect(pItem);
		delete pDetector;
		pDetector = nullptr;
		return iRet;
	}else{
		AsDebug() << typeid(_DETECTOR).name()<<"不是AsTestAlgorithmExecutor的子类";
		return AsDefine::AsError_FunctionCallException;
	}
}

/**
 * @desc 测试dll插件
 */
class ADF_EXPORT AsTestPlugin : public AsPlugin {
public:
	virtual ~AsTestPlugin() {}

protected:
	AsTestOutputArg m_out;
protected:
	/**
	 * 注册配置框
	 */
	template<typename _UITYPE>
	void registerConfigUiType() 
	{
		m_out.uiCtor= As::constructChild<_UITYPE, ATConfigUi>;
	}

	/**
	 * 注册参数类型
	 */
	template<typename _PARAMTYPE>
	void registerParamType() 
	{
		m_out.paramCtor = As::constructChild<_PARAMTYPE, AsJsonObject>;
	}

	/**
	 * 注册列表显示类型
	 */
	template<typename _MODELROWTYPE>
	void registerModelRowType()
	{
		m_out.modelItemCtor = As::constructChild<_MODELROWTYPE, AsPluginTableModelRow>;
	}

	// 添加执行函数
	void registerDetectFn(QString fnName, ATDetectFn fn);

	// 模板函数添加执行函数
	template<typename __DETECTORD>
	void registerDetectFn(QString fnName) 
	{
		if (!m_out.detectFnMap.contains(fnName)) {
			m_out.fnList << fnName;
		}
		m_out.detectFnMap[fnName] = &detectFn<__DETECTORD>;
	}

public:
	virtual void afterCall() override;
	/**
	 * @desc 设置构造器的入口函数，用户实现
	 */
	virtual void resolveCtorsFn();

public:
	static void resolveCtors(AsPlugin* pPlugin);

};
